<template>
  <div id="canvas-topology">
    <canvas id="topology" width="1000" height="2000"></canvas>
  </div>
</template>

<script>
export default {
  name: "topology",
  data() {
    return {
      treeData: [
        {
          name: "甘肃",
          children: [
            {
              name: "业务域1",
              // children: [
              //   {
              //     name: "1-1",
              //     children: [{ name: "1-1-1" }, { name: "1-1-2" }]
              //   },
              //   { name: "1-2" },
              //   { name: "1-3" },
              //   { name: "1-4" },
              //   { name: "1-5" },
              //   { name: "1-6" }
              // ]
            },
            // {
            //   name: "业务域2",
            //   children: [{ name: "2-1" }, { name: "2-2" }, { name: "2-3" }]
            // }
          ],
        },
        {
          name: "甘肃2",
          children: [
            {
              name: "业务域288",
              children: [
                { name: "1-1" },
                { name: "1-2" },
                { name: "1-3" },
                { name: "1-4" },
                { name: "1-5" },
                {
                  name: "1-6",
                  children: [{ name: "1-6-1" }, { name: "1-6-2" }],
                },
              ],
            },
            {
              name: "业务域299",
              // children: [{ name: "2-1" }, { name: "2-2" }, { name: "2-3" }]
            },
            {
              name: "业务域299",
              // children: [{ name: "2-1" }, { name: "2-2" }, { name: "2-3" }]
            },
          ],
        },
      ],
      lineWidth: 1,
      width: null, // 画布宽度
      height: null, // 画布高度
      ctx: null, //画笔
      iconList: [
        require("../../../assets/images/succ.png"),
        require("../../../assets/images/succ.png"),
        require("../../../assets/images/succ.png"),
        require("../../../assets/images/succ.png"),
      ],
      offsetX: 150, //横向相隔距离
      offsetY: 30, //纵向相隔距离
      imgW: 50, //图片宽度
      imgH: 50, //图片高度
      textSpace: 20, //图片和文字间距
    };
  },
  methods: {
    render() {
      let canvas = document.getElementById("topology");
      if (!canvas.getContext) {
        // console.log("不支持getContext");
        return;
      }

      this.width = canvas.offsetWidth;
      this.height = canvas.height;

      this.ctx = canvas.getContext("2d");

      // this.getDataTree(this.treeData, 0);

      this.renderItemForList(this.treeData, 0, 0, 0);

      console.log(this.treeData);
    },
    /**
     * 递归，从最后一层逆向计算每个节点所需占比
     * @param treeData
     * @param level 层级
     * @param x x坐标
     * @param y y坐标
     */
    renderItemForList(treeData, level, x, y) {
      let nums = 0;
      treeData.forEach((item) => {
        let height = this.offsetY + this.imgH + this.textSpace,
          width = this.offsetX + this.imgW,
          textH = this.imgH + this.textSpace;

        item.level = level + 1;
        item.x = x;
        item.y = y + height * nums;

        if (item.level > 1) {
          // 绘制横向连线
          this.renderLine("row", item.x, item.y);
        }

        if (item.children && item.children.length) {
          this.renderItemForList(
            item.children,
            level + 1,
            item.x + width,
            item.y
          );
          // 绘制横向连线
          this.renderLine("row", item.x, item.y, null, true);

          // 绘制竖向连线
          this.renderLine(
            "column",
            item.x,
            item.y,
            item.children[item.children.length - 1].y
          );
        }

        item.number = item.children?.length || 1; // 子节点数量

        // 计算当前节点所有子元素集合的最大长度
        item.total = item.children
          ? item.children.reduce((r, c) => {
              r += c.total ? c.total : c.number;
              return r;
            }, 0)
          : 0;

        nums += item.total > item.number ? item.total : item.number;
        this.ctx.restore();
        // 绘制icon
        this.renderItemIcon(this.iconList[level], item.x, item.y);
        // 绘制文字
        this.renderText(item.name, item.x + this.imgW / 2, item.y + textH);
      });
    },

    /**
     * 绘制icon
     * @param {*} imgPath 图片路径
     * @param {*} x x坐标
     * @param {*} y y坐标
     */
    renderItemIcon(imgPath, x, y) {
      let that = this,
        img = document.createElement("img");
      img.src = imgPath;

      img.onload = () => {
        that.ctx.save();
        that.ctx.beginPath();
        that.ctx.drawImage(img, x, y, this.imgW, this.imgH);
        that.ctx.restore();
      };
    },
    /**
     * 绘制文字
     * @param {*} name 名称
     * @param {*} x x坐标
     * @param {*} y y坐标
     */
    renderText(name, x, y) {
      this.ctx.beginPath();
      this.ctx.textAlign = "center";
      this.ctx.fillText(name, x, y);
      this.ctx.closePath();
    },
    /**
     * 计算线段位置并且渲染
     * @param {*} direction 线方向 row 横向 column 竖向
     * @param {*} x x坐标
     * @param {*} y y坐标
     * @param {*} endY y轴结束为止
     * @param {*} isNext 横向位置 左右线条
     */
    renderLine(direction, x, y, endY, isNext) {
      let sx, sy, ex, ey;
      if (direction === "column") {
        sx = x + this.imgH + this.offsetX / 2 - 10;
        sy = y + this.imgH / 2;
        ex = x + this.imgH + this.offsetX / 2 - 10;
        ey = endY + this.imgH / 2;
      } else {
        sx = isNext ? x + this.imgH : x;
        sy = y + this.imgH / 2;
        ex = isNext ? x + this.imgH + this.offsetX / 2 : x - this.offsetX / 2;
        ey = y + this.imgH / 2;
      }

      this.drawerLine(sx, sy, ex, ey);
    },

    /**
     * 绘制连线
     * @param {*} sx  x起点坐标
     * @param {*} sy  y起点坐标
     * @param {*} ex  x终点坐标
     * @param {*} ey  y终点坐标
     */
    drawerLine(sx, sy, ex, ey) {
      this.ctx.closePath();
      this.ctx.beginPath();
      this.ctx.setLineDash([20, 10]);
      this.ctx.lineWidth = 2;
      this.ctx.strokeStyle = "#60dbe6";
      this.ctx.moveTo(sx, sy);
      this.ctx.lineTo(ex, ey);
      this.ctx.stroke();
      this.ctx.closePath();
    },

    // render,
  },
  mounted() {
    this.render();
  },
};
</script>

<style scoped lang="scss">
#canvas-topology {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
